#include <iostream>
#include <string>

using std::cout;
using std::endl;
using std::string;

template <typename T, size_t kSize = 10>
class Queue
{
public:
    Queue()
    : _front(0)
    , _rear(0)
    , _data(new T[kSize]())
    {
        cout << "Queue()" << endl;
    }

    bool full() const;
    bool empty() const;
    void push(const T&value);
    void pop();
    T front();
    T back();
    ~Queue();

private:
    int _front;
    int _rear;
    T *_data;
};

template <typename T, size_t kSize>
bool Queue<T, kSize>::full() const
{
    return (_front == (_rear + 1) % kSize);
}

template <typename T, size_t kSize>
bool Queue<T, kSize>::empty() const
{
    return _front == _rear;
}

template <typename T, size_t kSize>
void Queue<T, kSize>::push(const T&value)
{
    if(!full())
    {
        _data[_rear++] = value;
        _rear %= kSize;
    }
    else
    {
        cout << "The queue is full" <<endl;
        return;
    }
}

template <typename T, size_t kSize>
void Queue<T, kSize>::pop()
{
    if(!empty())
    {
        ++_front;
        _front %= kSize;
    }
    else
    {
        cout << "The queue is empty" << endl;
        return;
    }
}

template <typename T, size_t kSize>
T Queue<T, kSize>::front()
{
    return _data[_front];
}

template <typename T, size_t kSize>
T Queue<T, kSize>::back()
{
    return _data[(_rear - 1 + kSize) % kSize];
}

template <typename T, size_t kSize>
Queue<T, kSize>::~Queue()
{
    cout << "~Queue()" <<endl;
    if(_data)
    {
        delete [] _data;
        _data = nullptr;
    }
}

void test()
{
    Queue<int> que;
    cout << "队列是不是空的？" << que.empty() << endl;
    que.push(1);
    cout << "队列是不是满的？" << que.full() << endl;

    for(int idx = 2; idx != 15; ++idx)
    {
        que.push(idx);
    }

    while(!que.empty())
    {
        cout << que.front() << "  ";
        que.pop();
    }
    cout << endl;
    cout << "栈是不是空的？" << que.empty() << endl;
}

void test2()
{
    Queue<string, 20> que;
    cout << "队列是不是空的？" << que.empty() << endl;
    que.push(string("aa"));
    cout << "队列是不是满的？" << que.full() << endl;

    for(int idx = 1; idx != 15; ++idx)
    {
        que.push(string(2, 'a' + idx));
    }
    cout << "队列是不是满的？" << que.full() << endl;

    while(!que.empty())
    {
        cout << que.front() << "  ";
        que.pop();
    }
    cout << endl;
    cout << "栈是不是空的？" << que.empty() << endl;
}

int main(int argc, char **argv)
{
    test();
    return 0;
}
